import path from 'path';
import router from 'koa-router';
import DBTool from '../com/DBTool/DBTool';
import configTool from '../com/configTool';
import FSTool from '../lib/FSTool/index';
import DBConnectTool from '../com/DBTool/DBConnectTool';
import CesiumTerrain from '../lib/GISServer/CesiumTerrain/CesiumTerrain';
import MapBoxTile from '../lib/GISServer/MapboxTile/MapboxTile';
import threadEncryptFiles from '../lib/FSTool/EncryptFiles/threadEncryptFiles/index';
import webSocketTool from '../com/webSocketTool/webSocketTool';
import getFilePathList from '../lib/FSTool/getFilePathList';
import TianDiTu from '../lib/GISServer/WMTSTile/TianDiTu';

const ManageRoutes = new router({ prefix: '/manage' });

ManageRoutes
    .get('/getDBInfoList', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let fileInfoList = await DBTool.getDBInfoList() || [];
        ctx.body = JSON.stringify(fileInfoList);
    })
    .get('/getDBPathTree', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDBPathTree();
        ctx.body = JSON.stringify(res);
    })
    .get('/getFileListByPath', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, path } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDirListByPath(path);
        ctx.body = JSON.stringify(res);
    })
    .get('/getDirInfo', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, dirPath } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        let res = await dbTool.getDirInfo(dirPath);
        ctx.body = JSON.stringify(res);
    })
    .get('/createDB', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, targetDirectory, mataData } = ctx.request.query;
        if (mataData) {
            mataData = JSON.parse(mataData);
        }
        let msg = await DBTool.createDB(DBName, targetDirectory, mataData);
        ctx.body = JSON.stringify({ msg });
    })
    .get('/appendFile', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, targetDirectory, currentDirectory } = ctx.request.query;
        let msg = await DBTool.appendFile(DBName, targetDirectory, currentDirectory);
        await DBConnectTool.reConnect(DBName);
        ctx.body = JSON.stringify({ msg });
    })
    .get('/clearFileDate', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.clearFileDate();
        ctx.body = JSON.stringify(res);
    })
    .get('/wipeCache', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.wipeCache();
        ctx.body = JSON.stringify(res);
    })
    .get('/deleteByFullPath', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, fullPath } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.deleteByFullPath(fullPath);
        ctx.body = JSON.stringify(res);
    })
    .get('/deleteByDir', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, directory } = ctx.request.query;
        let dbTool = await DBConnectTool.openDB(DBName);
        await DBConnectTool.reConnect(DBName);
        let res = await dbTool.deleteByDir(directory);
        ctx.body = JSON.stringify(res);
    })
    .get('/exportDB', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, targetDirectory } = ctx.request.query;
        let res = await DBTool.exportDB(DBName, targetDirectory);
        ctx.body = JSON.stringify({ res });
    })
    .get('/deleteDB', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName } = ctx.request.query;
        if (DBName) {
            await DBConnectTool.closeAll();
            let result = await DBTool.deleteDB(DBName);
            ctx.body = JSON.stringify({ result });
        } else {
            ctx.status = 404;
        }
    })
    .get('/getFileBySearch', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, text } = ctx.request.query;
        if (DBName && text) {
            let dbTool = await DBConnectTool.openDB(DBName);
            let list = await dbTool.getFileListBySearch(text);
            list.map((item: any) => item.ext = path.extname(item.file_name));
            ctx.body = JSON.stringify(list);
        } else {
            ctx.status = 404;
        }
    })
    .get('/threadEncryptFiles', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { inputPath, outPutPath, passWorld, threadNum } = ctx.request.query;
        if (inputPath && outPutPath && passWorld && threadNum) {
            const filePathList = await getFilePathList(inputPath);

            const beginTime = new Date().getTime();
            const mes = await threadEncryptFiles(filePathList, inputPath, outPutPath, passWorld, (e: any) => {
                e.action = 'runProgress';
                e.passTime = Math.ceil((new Date().getTime() - beginTime) / 1000);
                webSocketTool.send(JSON.stringify(e));
            }, threadNum);

            ctx.body = JSON.stringify(mes);
        } else {
            ctx.status = 400;
            ctx.body = JSON.stringify({ msg: '参数错误' });
        }
    })
    .get('/getClientServerWebLog', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        const [err, text] = await FSTool.readFileAsync(path.join(configTool.appBasePath, './temp/logs/clientServer/WebLog.json'));
        if (text) {
            ctx.body = JSON.parse(`[${text.toString().slice(0, -2)}]`);
        } else {
            ctx.body = [];
        }
    })
    .get('/getManageServerWebLog', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        const [err, text] = await FSTool.readFileAsync(path.join(configTool.appBasePath, './temp/logs/manageServerPort/WebLog.json'));
        if (text) {
            ctx.body = JSON.parse(`[${text.toString().slice(0, -2)}]`);
        } else {
            ctx.body = [];
        }
    })
    .get('/getLogSummary', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        const [err0, text0] = await FSTool.readFileAsync(path.join(configTool.appBasePath, './temp/logs/clientServer/WebLog.json'));
        const [err1, text1] = await FSTool.readFileAsync(path.join(configTool.appBasePath, './temp/logs/manageServerPort/WebLog.json'));
        const logSummaryMap = new Map<string, any>();
        if (text0 && text1) {
            const clientWebLog = JSON.parse(`[${text0.toString().slice(0, -2)}]`);
            const manageWebLog = JSON.parse(`[${text1.toString().slice(0, -2)}]`);

            clientWebLog.forEach((item: any) => {
                const ip = item.ip;
                const start = new Date(item.start).toDateString();
                const key = `${ip}-${start}`;
                if (logSummaryMap.has(key)) {
                    const value = logSummaryMap.get(key);
                    value.count++;
                } else {
                    const isoDate = new Date(start).toISOString().replace(/T.*/, '');
                    logSummaryMap.set(key, { ip, isoDate, count: 1 });
                }
            });
        }


        ctx.body = Array.from(logSummaryMap.values());

    })
    .post('/setMataData', async (ctx: any) => {
        ctx.set('Content-Type', 'application/json;charset=utf-8');
        let { DBName, mataData } = ctx.request.body;
        let dbTool = await DBConnectTool.openDB(DBName);
        if (mataData) {
            mataData = JSON.parse(mataData);
        }
        let msg = await dbTool.setMataData(mataData);
        ctx.body = JSON.stringify({ msg });
    })

    .get('/api.mapbox.com/v4/mapbox.satellite/:z/:x/:y.webp', async (ctx: any) => {
        let { z, x, y } = ctx.params;
        let [err, buffer] = await MapBoxTile.getSatelliteFileBuffer(z, x, y);

        if (buffer) {
            ctx.set('Content-Type', 'image/jpeg');
            ctx.body = buffer;
        } else {
            ctx.status = 422;
            ctx.set('Content-Type', 'application/json;charset=utf-8');
            ctx.body = err;
            console.log('代理 MapBoxTile 瓦片失败', z, x, y);
        }
    })
    .get('/api.mapbox.com/v4/mapbox.terrain-rgb/:z/:x/:y.png', async (ctx: any) => {
        let { z, x, y } = ctx.params;
        let [err, buffer] = await MapBoxTile.getTerrainRGBFileBuffer(z, x, y);

        if (buffer) {
            ctx.set('Content-Type', 'image/png');
            ctx.body = buffer;
        } else {
            ctx.status = 422;
            ctx.set('Content-Type', 'application/json;charset=utf-8');
            ctx.body = err;
            console.log('代理 MapBoxTile 瓦片失败', z, x, y);
        }
    })
    .get('/assets.cesium.com/1/:url(.*)', async (ctx: any) => {
        const url = ctx.params.url;
        let fileSavePath = path.join(configTool.appBasePath, 'temp/fileOut/assets.cesium.com/1/', url);

        // 判断是否有磁盘缓存文件
        let [err, buffer] = await FSTool.readFileAsync(fileSavePath);

        if (err) {
            // 从数据库或网络请求
            [err, buffer] = await CesiumTerrain.getFileBuffer(url);
        }


        if (buffer) {
            ctx.body = buffer;
        } else {
            ctx.status = 422;
            ctx.body = err;
            console.log(`代理 Cesium 官方地形数据失败，${ctx.url}`);
        }
    });

export default ManageRoutes;
